/**
 * Copyright 2010 upTick Pty Ltd
 *
 * Licensed under the terms of the GNU Lesser General Public License version 3 
 * as published by the Free Software Foundation. You may obtain a copy of the
 * License at: http://www.gnu.org/copyleft/lesser.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations 
 * under the License. 
 */

package au.com.uptick.serendipity.client;

import au.com.uptick.serendipity.client.gin.SerendipityGinjector;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.Dictionary;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.resources.client.CssResource.NotStrict;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
import com.gwtplatform.mvp.client.DelayedBindRegistry;
import com.gwtplatform.mvp.client.proxy.PlaceRequest;
import org.gwtmultipage.client.UrlPatternEntryPoint;

@UrlPatternEntryPoint(value = "((Serendipity.html)|(Account.html))(\\\\?locale=(en|de|fr))?((&|\\\\?)gwt.codesvr=127.0.0.1:9997)?")
public class Serendipity implements EntryPoint {

    interface GlobalResources extends ClientBundle {
        @NotStrict
        @Source("Serendipity.css")
        CssResource css();
    }

    private static SerendipityConstants constants;

    private static final SerendipityGinjector ginjector = GWT.create(SerendipityGinjector.class);

    private long startTimeMillis;

    public void onModuleLoad() {

        // Defer all application initialisation code to onModuleLoad2() so that the
        // UncaughtExceptionHandler can catch any unexpected exceptions.
        Log.setUncaughtExceptionHandler();

        DeferredCommand.addCommand(new Command() {
            public void execute() {
                onModuleLoad2();
            }
        });
    }

    private void onModuleLoad2() {
        try {

            if (!Log.isLoggingEnabled()) {
                Window.alert("Logging is disabled.");
            }

            // Use a code guard e.g. "if (Log.isDebugEnabled() {...}"
            // to ensure unnecessary code is complied out when log_level=OFF
            // or any log_level higher than DEBUG
            if (Log.isDebugEnabled()) {
                startTimeMillis = System.currentTimeMillis();
            }

            // No code guard necessary as the code will be
            // complied out when log_level=OFF
            Log.debug("onModuleLoad2()");
            // Log.trace("This is a 'TRACE' test message");
            // Log.info("This is a 'INFO' test message");
            // Log.warn("This is a 'WARN' test message");
            // Log.error("This is a 'ERROR' test message");
            // Log.fatal("This is a 'FATAL' test message");

            // inject global styles
            GWT.<GlobalResources>create(GlobalResources.class).css().ensureInjected();

            // load constants
            constants = (SerendipityConstants) GWT.create(SerendipityConstants.class);

            // this is required by gwt-platform proxy's generator
            DelayedBindRegistry.bind(ginjector);

            // get Host Page name
            Dictionary dictionary = Dictionary.getDictionary("Pages");
            revealCurrentPlace(dictionary.get("page"));

            // hide the animated 'loading.gif'
            RootPanel loading = RootPanel.get("loading");
            if (loading != null) {
                loading.setVisible(false);
            }

            // Use a code guard e.g. "if (Log.isDebugEnabled() {...}"
            // to ensure unnecessary code is complied out when log_level=OFF
            // or any log_level higher than DEBUG
            if (Log.isDebugEnabled()) {
                long endTimeMillis = System.currentTimeMillis();
                float durationSeconds = (endTimeMillis - startTimeMillis) / 1000F;
                Log.debug("Duration: " + durationSeconds + " seconds");
            }

        } catch (Exception e) {
            Log.error("e: " + e);
            e.printStackTrace();

            Window.alert(e.getMessage());
        }
    }

    // as per AccountsRecord
    private static final String ACCOUNT_ID = "accountId";
    private static final String ACTIVITY = "activity";

    private void revealCurrentPlace(String page) {

        PlaceRequest placeRequest = null;

        if (page.equals(NameTokens.mainPage)) {
            ginjector.getPlaceManager().revealCurrentPlace();
        } else if (page.equals(NameTokens.accountPage)) {

            String activity = Window.Location.getParameter(ACTIVITY);
            String accountId = Window.Location.getParameter(ACCOUNT_ID);

            placeRequest = new PlaceRequest(NameTokens.accountPage);
            placeRequest = placeRequest.with(ACTIVITY, activity).with(ACCOUNT_ID, accountId);
            ginjector.getPlaceManager().revealPlace(placeRequest);
        }
    }

    public static SerendipityConstants getConstants() {
        return constants;
    }

    public static SerendipityGinjector getSerendipityGinjector() {
        return ginjector;
    }
}
